﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace VolgaTransTelecomClient
{
    internal static class Security
    {
        #region Constants
        private const string Key = "{FC8885C6-6FF2-4D12-A380-9193C0156C96}";
        #endregion

        #region Methods
        /// <summary>
        /// Gets the hash.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>SHA-1 hash.</returns>
        internal static string GetHash(string value)
        {
            SHA1 hashGenerator = new SHA1CryptoServiceProvider();
            byte[] hash = hashGenerator.ComputeHash(Encoding.UTF8.GetBytes(value));
            return Convert.ToBase64String(hash);
        }

        /// <summary>
        /// Determines whether the specified value is match to the specified hash.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="hash">The hash.</param>
        /// <returns>Value indication whether the specified value is match to the specidied hash.</returns>
        internal static bool IsMatch(string value, string hash)
        {
            return GetHash(value).Equals(hash, StringComparison.Ordinal);
        }

        /// <summary>
        /// Encrypts the value.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>Encrypted string value.</returns>
        internal static string EncryptValue(string value)
        {
            byte[] result;
            using (ICryptoTransform encryptor = CreateEncryptor())
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    using (CryptoStream encryptStream = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
                    {
                        byte[] data = Encoding.UTF8.GetBytes(value);
                        encryptStream.Write(data, 0, data.Length);
                    }
                    result = stream.ToArray();
                }
            }
            return Convert.ToBase64String(result);
        }

        /// <summary>
        /// Decrypts the value.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>Decrypted value.</returns>
        internal static string DecryptValue(string value)
        {
            string result;
            using (ICryptoTransform decryptor = CreateDecryptor())
            {
                using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(value)))
                {
                    using (CryptoStream decryptStream = new CryptoStream(stream, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader reader = new StreamReader(decryptStream))
                        {
                            result = reader.ReadToEnd();
                        }
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// Creates the decryptor.
        /// </summary>
        /// <returns>The decryptor.</returns>
        private static ICryptoTransform CreateDecryptor()
        {
            RijndaelManaged algorithm = CreateCryptingAlgoritm();
            return algorithm.CreateDecryptor();
        }

        private static RijndaelManaged CreateCryptingAlgoritm()
        {
            RijndaelManaged result = new RijndaelManaged();
            byte[] salt = Encoding.UTF8.GetBytes(Key);
            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(Key, salt);
            result.Key = key.GetBytes(result.KeySize / 8);
            result.IV = key.GetBytes(result.BlockSize / 8);
            return result;
        }

        /// <summary>
        /// Creates the encryptor.
        /// </summary>
        /// <returns>The encryptor.</returns>
        private static ICryptoTransform CreateEncryptor()
        {
            RijndaelManaged algorithm = CreateCryptingAlgoritm();
            return algorithm.CreateEncryptor();
        }
        #endregion
    }
}
